package team.seekers.catering.user.service;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import team.seekers.catering.common.enums.FoodAmountTypeEnum;
import team.seekers.catering.common.enums.RoleEnum;
import team.seekers.catering.common.handler.exceptionHandler.ResultException;
import team.seekers.catering.common.utils.CateringUtil;
import team.seekers.catering.user.mapper.UserFitMapper;
import team.seekers.catering.user.entity.dao.User;
import team.seekers.catering.user.entity.dao.UserFit;
import team.seekers.catering.user.entity.dto.update.OfflineUserUpdateDTO;
import team.seekers.catering.user.entity.vo.info.EatLogAnalyzeInfoVO;
import team.seekers.catering.user.entity.vo.list.UserLogEatListVO;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;

/**
 * 服务实现类
 *
 * @author cbj
 * @author yiming
 */
@Service
public class UserFitService extends ServiceImpl<UserFitMapper, UserFit>{

    @Autowired
    private UserService userService;

    /**
     * 绑定身体数据成为线下用户（修改数据也走这个端口）
     */
    public void bindOffline(OfflineUserUpdateDTO offlineUserUpdateDTO) {
        String userId = CateringUtil.getUserId();
        UserFit userFit = getById(userId);
        if(userFit == null){
            userFit = new UserFit();
            BeanUtils.copyProperties(offlineUserUpdateDTO, userFit);
            userFit.setId(userId);

            // 计算bmi
            BigDecimal bmi = new BigDecimal(
                    offlineUserUpdateDTO.getWeight()*10000)
                    .divide(new BigDecimal(offlineUserUpdateDTO.getHeight()* offlineUserUpdateDTO.getHeight()),2, RoundingMode.HALF_UP);
            userFit.setBmi(bmi);

            // 能量参考摄入量
            BigDecimal simpleEnergy = new BigDecimal("0.0");
            if(offlineUserUpdateDTO.getSex() == 0){
                simpleEnergy = new BigDecimal("66.47").add(
                        new BigDecimal("13.57").multiply(new BigDecimal(offlineUserUpdateDTO.getWeight())).add(
                                new BigDecimal("5").multiply(new BigDecimal(offlineUserUpdateDTO.getHeight())).subtract(
                                        new BigDecimal("135.2")
                                )
                        )
                ).multiply(new BigDecimal("1.5"));
            }else if (offlineUserUpdateDTO.getSex() == 1){
                simpleEnergy = new BigDecimal("655.1").add(
                        new BigDecimal("9.46").multiply(new BigDecimal(offlineUserUpdateDTO.getWeight())).add(
                                new BigDecimal("1.85").multiply(new BigDecimal(offlineUserUpdateDTO.getHeight())).subtract(
                                        new BigDecimal("93.6")
                                )
                        )
                ).multiply(new BigDecimal("1.5"));
            }
            userFit.setSimpleEnergy(simpleEnergy.intValue());

            if(offlineUserUpdateDTO.getWish() == 0){
                // 计算减重信息
                userFit.setWeightStart(offlineUserUpdateDTO.getWeight());
                // 每天能量赤字
                BigDecimal dayEnergyLose = new BigDecimal("1100").multiply(new BigDecimal(
                        offlineUserUpdateDTO.getWeight() - offlineUserUpdateDTO.getWeightEnd())
                        .divide(new BigDecimal(offlineUserUpdateDTO.getWishWeeks()), 2, RoundingMode.HALF_UP));

                // 每日运动能耗
                BigDecimal daySportEnergyLose = new BigDecimal(offlineUserUpdateDTO.getWeight())
                        .multiply(new BigDecimal("1.05"))
                        .multiply(new BigDecimal(offlineUserUpdateDTO.getSport()))
                        .multiply(new BigDecimal(offlineUserUpdateDTO.getDayLong()));


                // 能量限制摄入量
                BigDecimal dayLimitEnergy = simpleEnergy.subtract(dayEnergyLose).add(daySportEnergyLose);
                userFit.setDayLimitEnergy(dayLimitEnergy.intValue());

            }else if(offlineUserUpdateDTO.getWish() == 1) {

            }


            userFit.setFoodType(getTypeBy(offlineUserUpdateDTO));
            save(userFit);

            User user = userService.getById(userId);
            if(user.getRole().getValue()<RoleEnum.USER_OFFLINE.getValue())
                user.setRole(RoleEnum.USER_OFFLINE);
            user.setFoodType(getTypeBy(offlineUserUpdateDTO));
            userService.updateById(user);
        }else {
            BeanUtils.copyProperties(offlineUserUpdateDTO, userFit);
            BigDecimal bmi = new BigDecimal(offlineUserUpdateDTO.getWeight()/(offlineUserUpdateDTO.getHeight()* offlineUserUpdateDTO.getHeight())*100000);
            userFit.setBmi(bmi);
            userFit.setId(userId);
            userFit.setFoodType(getTypeBy(offlineUserUpdateDTO));
            updateById(userFit);
        }
    }

    /**
     * 据身体数据计算推送的套餐种类
     */
    public FoodAmountTypeEnum getTypeBy(OfflineUserUpdateDTO offlineUserUpdateDTO){
        BigDecimal bmi = new BigDecimal(offlineUserUpdateDTO.getWeight()/(offlineUserUpdateDTO.getHeight()* offlineUserUpdateDTO.getHeight())*100000);
        double needKal = 0.0;
        if(offlineUserUpdateDTO.getSex() == 0){
            // 男性
            needKal = ((66.47+13.57* offlineUserUpdateDTO.getWeight()+5* offlineUserUpdateDTO.getHeight()-6.76*20)*1.25
                    + offlineUserUpdateDTO.getWeight()*1.05*(1.5+0.25* offlineUserUpdateDTO.getSport()))*0.4;
        }else{
            // 女性
            needKal = ((655.1+9.56* offlineUserUpdateDTO.getWeight()+1.85* offlineUserUpdateDTO.getHeight()-4.68*20)*1.25
                    + offlineUserUpdateDTO.getWeight()*1.05*(1.5+0.25* offlineUserUpdateDTO.getSport()))*0.4;
        }
        if (needKal < 600){
            if(offlineUserUpdateDTO.getWish() == 0){
                throw new ResultException().message("您的体脂比偏低，建议不要再减脂");
            }
            if(offlineUserUpdateDTO.getWish() == 1){
                return FoodAmountTypeEnum.MICRO_ENTRANCE;
            }
            if(offlineUserUpdateDTO.getWish() == 2){
                return FoodAmountTypeEnum.MICRO;
            }
        }else if(needKal < 700){
            if(offlineUserUpdateDTO.getWish() == 0){
                return FoodAmountTypeEnum.LOW_LOSE;
            }
            if(offlineUserUpdateDTO.getWish() == 1){
                return FoodAmountTypeEnum.LOW_ENTRANCE;
            }
            if(offlineUserUpdateDTO.getWish() == 2){
                return FoodAmountTypeEnum.LOW;
            }
        }else if(needKal <800){
            if(offlineUserUpdateDTO.getWish() == 0){
                return FoodAmountTypeEnum.MID_LOSE;
            }
            if(offlineUserUpdateDTO.getWish() == 1){
                return FoodAmountTypeEnum.MID_ENTRANCE;
            }
            if(offlineUserUpdateDTO.getWish() == 2){
                return FoodAmountTypeEnum.MID;
            }
        }else {
            if(offlineUserUpdateDTO.getWish() == 0){
                return FoodAmountTypeEnum.HIGH_LOSE;
            }
            if(offlineUserUpdateDTO.getWish() == 1){
                return FoodAmountTypeEnum.HIGH_ENTRANCE;
            }
            if(offlineUserUpdateDTO.getWish() == 2){
                return FoodAmountTypeEnum.HIGH;
            }
        }
        return null;
    }


    public EatLogAnalyzeInfoVO analyzeEatLog(EatLogAnalyzeInfoVO analyzeInfoVO) {
        UserFit userFit = getById(CateringUtil.getUserId());
        if(userFit.getWish() == 0){
            // 目标是减脂
            analyzeInfoVO.setWeightStart(userFit.getWeightStart());
            analyzeInfoVO.setWeight(userFit.getWeight());
            analyzeInfoVO.setWeightEnd(userFit.getWeightEnd());

            // 四餐能量分析
            Integer breakfast = 0;
            Integer launch = 0;
            Integer dinner = 0;
            Integer more = 0;

            if(analyzeInfoVO.getEatLogVOList().size() != 0){
                for (UserLogEatListVO userLogEatListVO : analyzeInfoVO.getEatLogVOList()) {
                    switch (userLogEatListVO.getType()){
                        case 0:
                            breakfast = breakfast + userLogEatListVO.getEnergy();
                            break;
                        case 1:
                            launch = launch + userLogEatListVO.getEnergy();
                            break;
                        case 2:
                            dinner = dinner + userLogEatListVO.getEnergy();
                            break;
                        case 3:
                            more = more + userLogEatListVO.getEnergy();
                            break;
                    }
                }
            }
            ArrayList<Integer> comboPercent = new ArrayList<>();
            comboPercent.add(
                    new BigDecimal(breakfast).divide(new BigDecimal(userFit.getDayLimitEnergy()-150),2,RoundingMode.HALF_UP)
                            .multiply(new BigDecimal("300")).intValue());
            comboPercent.add(new BigDecimal(launch).divide(new BigDecimal(userFit.getDayLimitEnergy()-150),2,RoundingMode.HALF_UP)
                    .multiply(new BigDecimal("400")).intValue());
            comboPercent.add(new BigDecimal(dinner).divide(new BigDecimal(userFit.getDayLimitEnergy()-150),2,RoundingMode.HALF_UP)
                    .multiply(new BigDecimal("300")).intValue());
            comboPercent.add(new BigDecimal(breakfast)
                    .divide(new BigDecimal("1.5"),2,RoundingMode.HALF_UP).intValue());

            analyzeInfoVO.setComboEnergyPercent(comboPercent);

            analyzeInfoVO.setDayLastLimitEnergy(userFit.getDayLimitEnergy()-breakfast-launch-dinner-more);
        }
        return analyzeInfoVO;
    }
}
